package com.sinoglobal.sinostore.adapter;

import android.annotation.SuppressLint;
import android.os.Build;
import android.util.SparseArray;
import android.view.View;

public class RecycleBin {

	/**
	 * 19 Views that were on screen at the start of layout. This array is
	 * populated at the start of
	 * 
	 * 20 layout, and at the end of layout all view in activeViews are moved to
	 * scrapViews.
	 * 
	 * 21 Views in activeViews represent a contiguous range of Views, with
	 * position of the first
	 * 
	 * 22 view store in mFirstActivePosition.
	 * 
	 * 23
	 */

	private View[] activeViews = new View[0];

	private int[] activeViewTypes = new int[0];

	/** Unsorted views that can be used by the adapter as a convert view. */

	private SparseArray<View>[] scrapViews;

	private int viewTypeCount;

	private SparseArray<View> currentScrapViews;

	public void setViewTypeCount(int viewTypeCount) {

		if (viewTypeCount < 1) {

			throw new IllegalArgumentException("Can't have a viewTypeCount < 1");

		}

		// noinspection unchecked

		SparseArray<View>[] scrapViews = new SparseArray[viewTypeCount];

		for (int i = 0; i < viewTypeCount; i++) {

			scrapViews[i] = new SparseArray<View>();

		}

		this.viewTypeCount = viewTypeCount;

		currentScrapViews = scrapViews[0];

		this.scrapViews = scrapViews;

	}

	protected boolean shouldRecycleViewType(int viewType) {

		return viewType >= 0;

	}

	/** @return A view from the ScrapViews collection. These are unordered. */

	View getScrapView(int position, int viewType) {

		if (viewTypeCount == 1) {

			return retrieveFromScrap(currentScrapViews, position);

		} else if (viewType >= 0 && viewType < scrapViews.length) {

			return retrieveFromScrap(scrapViews[viewType], position);

		}

		return null;

	}

	/**
	 * 63 Put a view into the ScrapViews list. These views are unordered.
	 * 
	 * 64
	 * 
	 * 
	 * 65
	 * 
	 * @param scrap
	 *            The view to add
	 * 
	 *            66
	 */

	@SuppressLint("NewApi")
	void addScrapView(View scrap, int position, int viewType) {

		if (viewTypeCount == 1) {

			currentScrapViews.put(position, scrap);

		} else {

			scrapViews[viewType].put(position, scrap);

		}

		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {

			scrap.setAccessibilityDelegate(null);

		}

	}

	/** Move all views remaining in activeViews to scrapViews. */

	@SuppressLint("NewApi")
	void scrapActiveViews() {

		final View[] activeViews = this.activeViews;

		final int[] activeViewTypes = this.activeViewTypes;

		final boolean multipleScraps = viewTypeCount > 1;

		SparseArray<View> scrapViews = currentScrapViews;

		final int count = activeViews.length;

		for (int i = count - 1; i >= 0; i--) {

			final View victim = activeViews[i];

			if (victim != null) {

				int whichScrap = activeViewTypes[i];

				activeViews[i] = null;

				activeViewTypes[i] = -1;

				if (!shouldRecycleViewType(whichScrap)) {

					continue;

				}

				if (multipleScraps) {

					scrapViews = this.scrapViews[whichScrap];

				}

				scrapViews.put(i, victim);

				if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {

					victim.setAccessibilityDelegate(null);

				}

			}

		}

		pruneScrapViews();

	}

	/**
	 * 114 Makes sure that the size of scrapViews does not exceed the size of
	 * activeViews.
	 * 
	 * 115 (This can happen if an adapter does not recycle its views).
	 * 
	 * 116
	 */

	private void pruneScrapViews() {

		final int maxViews = activeViews.length;

		final int viewTypeCount = this.viewTypeCount;

		final SparseArray<View>[] scrapViews = this.scrapViews;

		for (int i = 0; i < viewTypeCount; ++i) {

			final SparseArray<View> scrapPile = scrapViews[i];

			int size = scrapPile.size();

			final int extras = size - maxViews;

			size--;

			for (int j = 0; j < extras; j++) {

				scrapPile.remove(scrapPile.keyAt(size--));

			}

		}

	}

	static View retrieveFromScrap(SparseArray<View> scrapViews, int position) {

		int size = scrapViews.size();

		if (size > 0) {

			// See if we still have a view for this position.

			for (int i = 0; i < size; i++) {

				int fromPosition = scrapViews.keyAt(i);

				View view = scrapViews.get(fromPosition);

				if (fromPosition == position) {

					scrapViews.remove(fromPosition);

					return view;

				}

			}

			int index = size - 1;

			View r = scrapViews.valueAt(index);

			scrapViews.remove(scrapViews.keyAt(index));

			return r;

		} else {

			return null;

		}

	}
}
